// 这里代码很多价值，必须亲力亲为，自己写
// 路由守卫代码

// 导入 router 实例
import router from '@/router'
// 导入 store 实例
import store from '@/store'

// 导入 nprogress 模块（进入页面的加载提示）
import NProgress from 'nprogress'
// 导入 nprogress 的样式

// 白名单数组，这里放的是无需登录就可访问的路由路径
const whiteList = ['/login', '/404']

// 注册全局前置守卫
router.beforeEach(async(to, from, next) => {
  // 开启进度条的加载提示
  NProgress.start()
  // 从 vuex 中获取 token
  const { token } = store.state.user
  // 判断
  if (token) { // 登录了
    // 如果还要去登录
    if (to.path === '/login') {
      // 没必要去了，去首页
      next('/')
      // 关闭进度条的加载提示
      NProgress.done()
    } else {
      // 获取用户信息的action在这里调用
      // 注意：
      // 1. 此项目核心在权限控制，就是不同员工登录进来看到的主页菜单不同
      // 2. 如果员工登录成功了，已经跳转至主页在发请求，获取员工的角色权限已经太晚了
      // 3. 这个获取员工的角色权限信息的时机是在跳转至主页之前，拿到当前员工的角色信息，知道你是谁了，
      //    有哪些权限，然后在对应的开放左侧菜单，这些操作都做完了，在让员工跳转至主页，这个时候ta所
      //    看到的左侧菜单就是ta具备的权限
      // 4. 只是现在还不知道如何开放对应的左侧菜单，这个点先留着，大概的原理就是根据员工的角色列表信息
      //    动态筛选动态路由表即可实现

      // 这个地方代码当路由切换的时候会多次执行，会发起多次取消请求，需要优化
      // 如果没有用户信息，才发起请求
      // 第1种解决方式：判断vuex中的userId有没有
      if (!store.state.user.userInfo.userId) {
        // await关键字的目的是等待action函数执行完毕，才继续往后执行（异步变同步）
        await store.dispatch('user/getUserInfoAction')
        // 获取当前用户的menus数组
        const { menus } = store.state.user.userInfo.roles
        // 基于当前用户信息中 roles.menus 数组来筛选动态路由表
        // 筛选的条件：判断当前路由第一个children的名字是否在menus数组中
        // 在的话，就留下(拥有的权限/菜单，开放)；否则就过滤掉了，舍去了(不开放)
        // 触发route/filterAsyncRouteAction这个函数，拿到筛选后动态路由表
        const showAsyncRoutes = await store.dispatch('route/filterAsyncRouteAction', menus)
        console.log('showAsyncRoutes', showAsyncRoutes)
        // 把筛选的结果在动态追加到路由表中
        // router.addRoutes(路由对象数组): 同时追加多个路由规则到路由表中
        // router.addRoute(路由对象): 追加1个路由规则到路由表中
        // 把筛选的动态路由结果加入到路由表中，这样今后输入path，才能访问到compoennt
        // 否则就算知道路由path，访问仍然会404
        router.addRoutes([
          ...showAsyncRoutes,
          { path: '*', redirect: '/404', hidden: true }
        ])
        console.log('222', router)
        // 刷新一下路由表，重新进入一次
        return next({
          ...to, // 保留原有的所有要去的路由信息
          replace: true // 替换刚才那一次跳转的历史记录
        })
      }
      // 第2种解决方式：拿到action函数的返回值
      // 注意：所有的action函数返回值都是Promise实例，要接收action函数的返回值，需要配合await关键字
      // const userObj = await store.dispatch('user/getUserInfoAction')
      // 判断userObj中是否存在userId，如果没有再发请求
      // 否则放行
      next()
    }
  } else { // 未登录
    // 进一步判断，要去的路由路径是否在白名单中
    if (whiteList.includes(to.path)) { // 如果在
      // 放行
      next()
    } else { // 否则
      // 跳转至登录，并携带回跳地址
      next(`/login?redirectUrl=${to.path}`)
      // 关闭进度条的加载提示
      NProgress.done()
    }
  }
})

// 注册全局后置守卫
router.afterEach(() => {
  // 关闭进度条的加载提示
  NProgress.done()
})

// 按钮的操作权控制：
// 1. 移除或显示(v-if="条件")
// 2. 禁用(:disasble="!条件")
// 3. 显示，也不禁用，给出无权操作的提示
